package com.common.utils.date;

import sun.applet.Main;

import java.io.Serializable;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;

/**
 * 时间处理的工具类
 * @author zengliang
 */
public class DateUtil implements Serializable
{
	
	private static final long serialVersionUID = 8017123033671694211L;

	 /**
	  * 取得当前日期的年份，以yyyy格式返回.
	  * @return 当年 yyyy   
	  */  
	public static String getCurrentYear() {   
		return getFormatCurrentTime("yyyy"); 
	} 
	
	 /**   
	  * 自动返回上一年。例如当前年份是2007年，那么就自动返回2006 
	  * @return 返回结果的格式为 yyyy   
	  */  
	public static String getBeforeYear() {  
		String currentYear = getFormatCurrentTime("yyyy");   
		int beforeYear = Integer.parseInt(currentYear) - 1;   
		return "" + beforeYear;  
	}   
	
	/**   
	 * 取得当前日期的月份，以MM格式返回.   
	 * @return 当前月份 MM   
	 */  
	public static String getCurrentMonth() {   
		return getFormatCurrentTime("MM");  
	}
	
	/**   
	 * 取得当前日期的天数，以格式"dd"返回.  
	 * @return 当前月中的某天dd   
	 */  
	public static String getCurrentDay() {   
		return getFormatCurrentTime("dd");  
	}   
	
	/**   
	 * 返回当前时间字符串。
	 * 格式：yyyy-MM-dd 
     * @return String 指定格式的日期字符串.   
     */  
	public static String getCurrentDate() {   
		return getFormatDateTime(new Date(), "yyyy-MM-dd");  
	}
	
	 /**   
	  * 返回当前指定的时间戳。格式为yyyy-MM-dd HH:mm:ss   
	  * @return 格式为yyyy-MM-dd HH:mm:ss，总共19位。 
	  */
	public static String getCurrentDateTime() {   
		return getFormatDateTime(new Date(), "yyyy-MM-dd HH:mm:ss");  
	}
	  
	/**   
	 * 根据给定的格式，返回时间字符串
	 * 格式参照类描绘中说明,和方法getFormatDate是一样
	 * @param format   日期格式字符串  
	 * @return String 指定格式的日期字符串. 
	 */  
	public static String getFormatCurrentTime(String format) {   
		return getFormatDateTime(new Date(), format);  
	}
	
	/**   
	 * 根据制定的格式，返回日期字符串。例如2007-05-05
	 * @param format   "yyyy-MM-dd" 或者 "yyyy/MM/dd",当然也可以是别的形式。  
	 * @return 指定格式的日期字符串。   
	 */  
	public static String getFormatDate(String format) {   
		return getFormatDateTime(new Date(), format);  
	}
	
	/**   
	 * 返回当前时间字符串。 
	 * 格式：yyyy-MM-dd HH:mm:ss  
	 * @return String 指定格式的日期字符串.   
	 */  
	public static String getCurrentTime() {   
		return getFormatDateTime(new Date(), "yyyy-MM-dd HH:mm:ss"); 
	}
	
	/**   
	 * 根据给定的格式与时间(Date类型的)，返回时间字符串
	 * @param date   指定的日期   
	 * @param format  日期格式字符串   
	 * @return String 指定格式的日期字符串.   
	 */  
	public static String getFormatDateTime(Date date, String format) {   
		SimpleDateFormat sdf = new SimpleDateFormat(format);   
		return sdf.format(date);  
	}
	
	/**
	 * 获取当前系统时间，并格式化
	 * @param rules 时间样式: 例如--> yyyy-MM-dd 或 yyyy/MM/dd
	 * @return
	 */
	public static String getCurrentDate(String rules) { 
		SimpleDateFormat sdf = new SimpleDateFormat(rules);
		return sdf.format(new Date());
	}
	
	/**   
	 * 格式化日期显示格式   
	 * @param sdate  原始日期格式 s - 表示 "yyyy-mm-dd" 形式的日期的 String 对象   
	 * @param format  格式化后日期格式  
	 * @return 格式化后的日期显示   
	 */  
	public static String dateFormat(String sdate, String format) {   
		SimpleDateFormat formatter = new SimpleDateFormat(format);   
		java.sql.Date date = java.sql.Date.valueOf(sdate);   
		String dateString = formatter.format(date);    
		return dateString; 
	}
	
	/**   
	 * 求两个日期相差天数 
	 * @param sd  起始日期，格式yyyy-MM-dd
     * @param ed 终止日期，格式yyyy-MM-dd   
     * @return 两个日期相差天数 
     */  
	public static long getIntervalDays(String sd, String ed) {   
		return ((java.sql.Date.valueOf(ed)).getTime() - (java.sql.Date.valueOf(sd)).getTime())/ (3600 * 24 * 1000);  
	}

	/**
	 * 两月相差数
	 * 起始年月yyyy-MM与终止月yyyy-MM之间跨度的月数
	 * @param beginMonth  格式为yyyy-MM
	 * @param endMonth    格式为yyyy-MM
	 * @return   整数
	 */
	public static int getInterval(String beginMonth, String endMonth) {   
		int intBeginYear = Integer.parseInt(beginMonth.substring(0, 4));   
		int intBeginMonth = Integer.parseInt(beginMonth.substring(beginMonth.indexOf("-") + 1));   
		int intEndYear = Integer.parseInt(endMonth.substring(0, 4));   
		int intEndMonth = Integer.parseInt(endMonth.substring(endMonth.indexOf("-") + 1));    
		return ((intEndYear - intBeginYear) * 12)+ (intEndMonth - intBeginMonth) + 1;  
	}
	
	/**   
	 * 获取指定日期的下一天。
	 * @param date  yyyy/MM/dd   
	 * @return yyyy/MM/dd   
	 */  
	public static String getDateTomorrow(String date) {      
		Date tempDate = null;   
		if(date.indexOf("/")>0){  
			tempDate = getDateObj(date, "[/]"); 
		}
		if(date.indexOf("-")>0){
			tempDate = getDateObj(date, "[-]");
		}
		tempDate = getDateAdd(tempDate, 1);
		return getFormatDateTime(tempDate, "yyyy/MM/dd");  
	}
	
	/**   
	 * 获取与指定日期相差指定天数的日期
	 * @param date   yyyy/MM/dd   
	 * @param offset   正整数   
	 * @return yyyy/MM/dd   
	 */  
	public static String getDateOffset(String date, int offset) {    
		//Date tempDate = getDateObj(date, "[/]");   
		Date tempDate = null;   
		if(date.indexOf("/")>0){
			tempDate = getDateObj(date, "[/]");
		}
		if(date.indexOf("-")>0){
			tempDate = getDateObj(date, "[-]");
		}
		tempDate = getDateAdd(tempDate, offset);
		return getFormatDateTime(tempDate, "yyyy/MM/dd");  
	}
	
	/**   
	 * 取得指定分隔符分割的年月日的日期对象.  
	 * @param argsDate   格式为"yyyy-MM-dd"   
	 * @param split   时间格式的间隔符，例如“-”，“/”，要和时间一致起来。  
	 * @return 一个java.util.Date()类型的对象   
	 */  
	public static Date getDateObj(String argsDate, String split) {   
		String[] temp = argsDate.split(split);   
		int year = new Integer(temp[0]).intValue();   
		int month = new Integer(temp[1]).intValue();   
		int day = new Integer(temp[2]).intValue();   
		return getDateObj(year, month, day);  
	}
	
	/**
	 * 取得指定年月日的日期对象
	 * @param year  年
	 * @param month  月    从1到12
	 * @param day    日
	 * @return   一个java.util.Date()类型的对象
	 */
	public static Date getDateObj(int year, int month, int day) {   
		Calendar c = new GregorianCalendar();   
		c.set(year, month - 1, day);   
		return c.getTime();  
	}
	
	/**
	 * 取得给定日期加上一定天数后的日期对象.
	 * @param date   给定的日期对象 
	 * @param amount  需要添加的天数，如果是向前的天数，使用负数就可
	 * @return   加上一定天数以后的Date对象
	 */
	public static Date getDateAdd(Date date, int amount) {   
		Calendar cal = new GregorianCalendar();   
		cal.setTime(date);   
		cal.add(GregorianCalendar.DATE, amount);   
		return cal.getTime();  
	}
	
	 /**   
	  * 获得当前日期固定间隔天数的日期，如前60天dateAdd(-60)
	  * @param amount   距今天的间隔日期长度，向前为负，向后为正   
	  * @param format   输出日期的格式.   
	  * @return java.lang.String 按照格式输出的间隔的日期字符串.   
	  */  
	public static String getFormatCurrentAdd(int amount, String format) {    
		Date d = getDateAdd(new Date(), amount);    
		return getFormatDateTime(d, format);  
	}
	
	/**   
	 * 取得给定日期加上一定天数后的日期对象.
	 * @param date   给定的日期对象   
	 * @param amount  需要添加的天数，如果是向前的天数，使用负数就可以.   
	 * @param format  输出格式.   
	 * @return Date 加上一定天数以后的Date对象.  
	 */  
	public static String getFormatDateAdd(Date date, int amount, String format) {   
		Calendar cal = new GregorianCalendar();   
		cal.setTime(date);   
		cal.add(GregorianCalendar.DATE, amount);   
		return getFormatDateTime(cal.getTime(), format);  
	}
	
	/**   
	 * 返回指定日期的前一天
	 * @param sourceDate   
	 * @param format    yyyy MM dd hh mm ss   
	 * @return 返回日期字符串，形式和formcat一致
	 */  
	public static String getYestoday(String sourceDate, String format) {   
		return getFormatDateAdd(getDateFromString(sourceDate, format), -1, format);  
	}   
	/**   
	 * 返回明天的日期
	 * @param format   
	 * @return 返回日期字符串，形式和formcat一致
	 */  
	public static String getFormatTomorrow(String format) {   
		return getFormatCurrentAdd(1, format);  
	}
	
	/**   
	 * 返回指定日期的后一天
	 * @param sourceDate  
	 * @param format   
	 * @return 返回日期字符串，形式和formcat一致
     */  
	public static String getFormatDateTommorrow(String sourceDate, String format) {  
		return getFormatDateAdd(getDateFromString(sourceDate, format), 1, format);  
    }
	
	/**   
	 * 返回两个日期之间相差多少天
	 * 注意开始日期和结束日期要统一起来
	 * @param startDate   格式"yyyy/MM/dd" 或者"yyyy-MM-dd"   
	 * @param endDate   格式"yyyy/MM/dd" 或者"yyyy-MM-dd"   
	 * @return 整数
	 */  
	public static int getDiffDays(String startDate, String endDate) {   
		long diff = 0;   
		SimpleDateFormat ft =null;   
		if(startDate.indexOf("/")>0&&endDate.indexOf("/")>0){    
			ft = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");   
		}   
		if(startDate.indexOf("-")>0&&endDate.indexOf("-")>0){    
			ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   
		}   
		try {    
			Date sDate = ft.parse(startDate + " 00:00:00");    
			Date eDate = ft.parse(endDate + " 00:00:00");    
			diff = eDate.getTime() - sDate.getTime();    
			diff = diff / 86400000;// 1000*60*60*24;   
			} catch (ParseException e) {    
				e.printStackTrace();   
			}   
		return (int) diff;
	}
	
	/**   
	 * 取得给定字符串描述的日期对象，描述模式采用pattern指定的格式.
	 * @param dateStr   日期描述 从给定字符串的开始分析文本，以生成一个日期。该方法不使用给定字符串的整个文本。 
	 * 有关日期分析的更多信息，请参阅    parse(String, ParsePosition) 方法
	 * 一个 String，应从其开始处进行分析  
	 * @param pattern   日期模式   
	 * @return 给定字符串描述的日期对象。   
	 */  
	public static Date getDateFromString(String dateStr, String pattern) {   
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);   
		Date resDate = null;   
		try {    
			resDate = sdf.parse(dateStr);   
		} catch (Exception e) {   
			e.printStackTrace();   
		}   
		return resDate;
	}

	/**
	 * 返回当月所有日期
	 * @param dateStr 格式：yyyymm
	 * @return List<String>
	 */
	public static List<String> getMonthFullDay(String dateStr){
		Calendar date = Calendar.getInstance();
		Integer year = Integer.parseInt(dateStr.substring(0, 4));
		Integer month = Integer.parseInt(dateStr.substring(4, dateStr.length()));
		SimpleDateFormat dateFormatYYYYMMDD = new SimpleDateFormat("yyyyMMdd");
		List<String> fullDayList = new ArrayList<>(32);
		// 获得当前日期对象
		Calendar cal = Calendar.getInstance();
		cal.clear();// 清除信息
		cal.set(Calendar.YEAR, year);
		// 1月从0开始
		cal.set(Calendar.MONTH, month-1 );
		// 当月1号
		cal.set(Calendar.DAY_OF_MONTH,1);
		int count = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		for (int j = 1; j <= count ; j++) {
			fullDayList.add(dateFormatYYYYMMDD.format(cal.getTime()));
			cal.add(Calendar.DAY_OF_MONTH,1);
		}
		return fullDayList;
	}

	/**
	 * excel时间格式类似：1-Sep-21转换为 yyyy-mm-dd
	 * @param date
	 * @return
	 */
	public static String getDatetimeShift(String date){
		DateTimeFormatter parseFormatter = new DateTimeFormatterBuilder()
				.parseCaseInsensitive()
				.appendPattern("d-MMM-yy")
				.toFormatter(Locale.ENGLISH);
		String datetime = LocalDate.parse(date, parseFormatter).format(DateTimeFormatter.BASIC_ISO_DATE);
		return datetime;
	}


	/**
	 * JDK8.0
	 * LocalDateTime 一些常用的转化大全
	 * @return
	 */
	public static void LocalDateTime(){
		LocalDateTime now1 = LocalDateTime.now();
		LocalDate date1 = now1.toLocalDate();
		LocalTime time1 = now1.toLocalTime();
		LocalDate now2 = LocalDate.now();
		LocalDateTime date2 = now2.atStartOfDay();
		String format = now1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime LocalTime = LocalDateTime.parse("2022-04-21 12:27:52",df);

		LocalDateTime format2 = null;
		try {
			SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			Date date = simple.parse("2022-04-21 12:27:52");
			format2 = new Timestamp(date.getTime()).toLocalDateTime();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		Long newSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
		System.out.println("LocalDateTime转LocalDate：" + date1);
		System.out.println("LocalDateTime转LocalTime：" + time1);
		System.out.println("LocalDate转LocalDateTime：" + date2);
		System.out.println("LocalDateTime格式化年月日：" + format);
		System.out.println("LocalDateTime格式化年月日时分秒：" + format2);
		System.out.println("获取毫秒时间：" + newSecond);
	}

}
